﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraPivotGrid;
using DevExpress.XtraPivotGrid.Customization;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using DevExpress.Utils;
using DevExpress.XtraGrid.Views.Layout;
using DevExpress.XtraGrid.Views.Card;
using System.Xml;
using System.Xml.XPath;
using DevExpress.XtraTreeList.Columns;
using efuture.http;
using efuture.xml;
using efuture.utils;


namespace efuture.vdrp
{

    public partial class frmReportDesign : DevExpress.XtraEditors.XtraForm
    {
        const String TYPE_TABLE = "table", TYPE_PIVOT = "pivot";
        static String ConfigRoot = Application.StartupPath + "\\";

        Boolean isNew = false;
        String ModelId, ModelName;
        Boolean Modified = false;
        public String ReportId, ReportParentId, ReportType, ReportCaption, ReportComments, ReportContents;

        public frmReportDesign()
        {
            InitializeComponent();
            ReportId = ReportParentId = "0";
            ReportContents = String.Empty;
            ReportType = ReportCaption = ReportComments = String.Empty;
        }

        Object DataSetControl
        {
            get
            {
                return TYPE_TABLE.Equals(ReportType) ? (Object)gridViewDesigner : (Object)pivotGridControlDesigner;
            }
        }

        delegate void DataSetFilledCallback(DataSet dataSet);

        void FillDataSetAsync(DataSetFilledCallback callback)
        {
            BackgroundWorker workerDataSetFiller = new BackgroundWorker();
            workerDataSetFiller.DoWork += GetDataSetAsync;
            workerDataSetFiller.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs e)
            {
                callback(e.Error == null ? (DataSet)e.Result : null);
            };
            workerDataSetFiller.RunWorkerAsync();
            workerDataSetFiller.Dispose();
        }

        void GetDataSetAsync(object sender, DoWorkEventArgs e)
        {
            using (WaitDialogForm wdf = new WaitDialogForm())
            {
                wdf.Caption = "Loading data...";
                String xmlData = "";
                xmlData = "<ReportInfo><Fields>{0}</Fields><DataModel>{1}</DataModel><MaxResults>100</MaxResults><Conditions><Condition><Field>Sale_date</Field><Op>=</Op><Value>date'2010-5-1'</Value></Condition></Conditions></ReportInfo>";
                xmlData = XMLHelper.SetXml(String.Format(xmlData, frmReportFilter.GetFields(DataSetControl), ModelName));
                xmlData = HttpHelper.DoPost("/rest/report/custom/query", xmlData, null);

                DataSet ds = new DataSet();
                ds.ReadXmlSchema(ConfigRoot + ModelName + ".xsd");
                ds.ReadXml(new StringReader(xmlData));
                e.Result = ds;
            }
        }

        static void AsyncInitializationCompleted(AsyncOperationResult result)
        {
            if (result == null)
            {
                //maybe error
            }

        }

        static void ResetGrid(GridControl gridControl1, GridView gridView1)
        {
            gridView1.ClearGrouping();
            gridView1.Columns.Clear();
            gridView1.GroupSummary.Clear();
            gridView1.FormatConditions.Clear();
            gridControl1.DataSource = null;
        }

        static void ResetPivotGrid(PivotGridControl pivotGridControl1)
        {
            pivotGridControl1.Groups.Clear();
            pivotGridControl1.Fields.Clear();
            pivotGridControl1.FormatConditions.Clear();
            pivotGridControl1.DataSource = null;
        }

        private void wizardControl1_NextClick(object sender, DevExpress.XtraWizard.WizardCommandButtonClickEventArgs e)
        {
            String xmlData = "";

            if (e.Page == this.wp1Welcome)
            {
                DataSet ds = new DataSet();
                ds.ReadXmlSchema(ConfigRoot + "ReportType.xsd");
                ds.ReadXml(ConfigRoot + "ReportType.data.xml");

                this.cardView1.DataSource = ds.Tables[0].DefaultView;
                LayoutView lv = (LayoutView)cardView1.DefaultView;

                xmlData = HttpHelper.DoGet(String.Format("/rest/report/custom/get?id={0}", ReportId), null);
                ReportType = XMLHelper.SelectSingleValue(xmlData, "/Root/Report/Type");
                if (String.IsNullOrEmpty(ReportType))
                {
                    isNew = true;
                    lv.ActiveFilterString = "";
                    ReportId = VdrpUtils.getIdentity();
                }
                else
                {
                    isNew = false;
                    lv.ActiveFilterString = String.Format("[{0}] = '{1}'", colReportType.FieldName, ReportType);

                    ReportId = XMLHelper.SelectSingleValue(xmlData, "/Root/Report/Id");
                    ModelId = XMLHelper.SelectSingleValue(xmlData, "/Root/Report/ModelId");
                    ReportCaption = XMLHelper.SelectSingleValue(xmlData, "/Root/Report/Caption");
                    ReportComments = XMLHelper.SelectSingleValue(xmlData, "/Root/Report/Comments");
                    ReportContents = XMLHelper.SelectSingleValue(xmlData, "/Root/Report/Contents");

                    ColumnView cv = (ColumnView)cardView1.FocusedView;
                    if (cv != null)
                    {
                        cv.SetFocusedRowCellValue(colReportCaption, ReportCaption);
                        cv.SetFocusedRowCellValue(colReportComments, ReportComments);
                    }
                }
            }
            else if (e.Page == this.wp2ReportType)
            {
                ColumnView cv = (ColumnView)cardView1.FocusedView;

                if (String.IsNullOrEmpty(Convert.ToString(cv.GetFocusedRowCellValue(colReportCaption))))
                {
                    e.Handled = true;
                    MessageBox.Show("Report Caption is null");
                    return;
                }
                ReportCaption = Convert.ToString(cv.GetFocusedRowCellValue(colReportCaption));
                ReportComments = Convert.ToString(cv.GetFocusedRowCellValue(colReportComments));

                if (String.IsNullOrEmpty(cv.GetFocusedRowCellValue(colReportType).ToString()))
                {
                    e.Handled = true;
                    MessageBox.Show("Report Type is null");
                    return;
                }

                ReportType = cv.GetFocusedRowCellValue(colReportType).ToString();
                if (String.IsNullOrEmpty(ModelId))
                {
                    xmlData = HttpHelper.DoGet("/rest/report/model/find", null);
                }
                else
                {
                    xmlData = HttpHelper.DoGet(String.Format("/rest/report/model/find?ModelId={0}", ModelId), null);
                }

                DataSet ds = new DataSet();
                ds.ReadXmlSchema(ConfigRoot + "DataModel.xsd");
                ds.ReadXml(new StringReader(xmlData));
                this.edtDataModel.Properties.DataSource = ds.Tables[0];
            }
            else if (e.Page == this.wp3DataSources)
            {
                if (String.IsNullOrEmpty(this.edtDataModel.Text))
                {
                    e.Handled = true;
                    MessageBox.Show("DataSource is null");
                    return;
                }

                // 
                this.pnlGridSetting.Visible = false;
                this.pnlPivotGridSetting.Visible = false;
                this.pnlPivotGridSetting.Controls.Clear();

                //
                this.pnlDesigner.SplitterPosition = wp4ReportDesigner.Width * 2 / 3;

                //
                this.gridControlDesigner.Visible = false;
                this.pivotGridControlDesigner.Visible = false;

                if (TYPE_TABLE.Equals(ReportType))
                {
                    // 
                    this.pnlGridSetting.Visible = true;
                    this.pnlGridSetting.Dock = DockStyle.Fill;
                    this.gridControlDesigner.Visible = true;
                    this.gridControlDesigner.Dock = System.Windows.Forms.DockStyle.Fill;

                    InitGrid(treeListFields, this.gridControlDesigner, this.gridViewDesigner, AsyncInitializationCompleted);
                }
                else if (TYPE_PIVOT.Equals(ReportType))
                {
                    // 
                    this.pnlPivotGridSetting.Visible = true;
                    this.pnlPivotGridSetting.Dock = DockStyle.Fill;
                    this.pivotGridControlDesigner.Visible = true;
                    this.pivotGridControlDesigner.Dock = System.Windows.Forms.DockStyle.Fill;
                    this.pivotGridControlDesigner.OptionsCustomization.AllowFilterInCustomizationForm = true;
                    this.pivotGridControlDesigner.OptionsCustomization.AllowSortInCustomizationForm = true;
                    this.pivotGridControlDesigner.OptionsCustomization.CustomizationFormStyle = CustomizationFormStyle.Excel2007;
                    this.pivotGridControlDesigner.FieldsCustomization(this.pnlPivotGridSetting);

                    InitPivotGrid(treeListFields, this.pivotGridControlDesigner, AsyncInitializationCompleted);
                }
            }
            else if (e.Page == this.wp4ReportDesigner)
            {
                if (TYPE_TABLE.Equals(ReportType))
                {
                    InitPreview(this.gridControlDesigner);
                }
                else if (TYPE_PIVOT.Equals(ReportType))
                {
                    InitPreview(this.pivotGridControlDesigner);
                }
            }
        }

        private void InitPreview(Control control1)
        {
            if (control1 == null)
            {
                return;
            }

            //
            this.gridControlPreview.Visible = false;
            ResetGrid(this.gridControlPreview, this.gridViewPreview);

            //
            this.pivotGridControlPreview.Visible = false;
            ResetPivotGrid(this.pivotGridControlPreview);

            DataSetFilledCallback callback = delegate(DataSet dataSet)
            {
                if (dataSet == null)
                {
                    return;
                }
                InitPreviewAsync(control1, dataSet);
            };

            FillDataSetAsync(callback);
        }

        private void InitPreviewAsync(Control control1, DataSet ds)
        {
            if (typeof(GridControl) == control1.GetType())
            {
                GridControl gridControl1 = (GridControl)control1;
                GridView gridView1 = (GridView)gridControl1.MainView;
                Dictionary<String, GridColumn> ColumnMap = new Dictionary<string, GridColumn>();

                //gridView1.SaveLayoutToXml("c:/gv.xml");

                this.gridViewPreview.OptionsView.ShowGroupPanel = gridView1.OptionsView.ShowGroupPanel;
                this.gridViewPreview.IndicatorWidth = 15;
                this.gridViewPreview.CustomDrawRowIndicator -= this.GridViewCustomDrawRowIndicator;
                this.gridControlPreview.Visible = true;
                this.gridControlPreview.Dock = DockStyle.Fill;

                // OptionsView
                gridViewPreview.OptionsView.AllowCellMerge = gridView1.OptionsView.AllowCellMerge;
                gridViewPreview.OptionsView.ShowHorzLines = gridView1.OptionsView.ShowHorzLines;
                gridViewPreview.OptionsView.ShowVertLines = gridView1.OptionsView.ShowVertLines;
                gridViewPreview.OptionsView.ShowGroupPanel = gridView1.GroupedColumns.Count > 0;

                // 按VisibleIndex排序
                GridColumn[] Columns = (GridColumn[])new ArrayList(gridView1.Columns).ToArray(typeof(GridColumn));
                Array.Sort(Columns, delegate(GridColumn f1, GridColumn f2)
                {
                    return f1.VisibleIndex.CompareTo(f2.VisibleIndex);
                });

                this.gridControlPreview.BeginUpdate();
                this.gridViewPreview.BeginUpdate();
                foreach (GridColumn gc in Columns)
                {
                    //if (gc.Visible)
                    {
                        GridColumn gridColumn = this.gridViewPreview.Columns.Add();
                        gridColumn.Caption = gc.Caption;
                        gridColumn.FieldName = gc.FieldName;
                        gridColumn.Visible = gc.Visible;
                        gridColumn.Tag = gc.Tag;
                        gridColumn.Width = gc.Width;
                        gridColumn.MinWidth = gc.Width;
                        gridColumn.UnboundType = gc.UnboundType;
                        gridColumn.UnboundExpression = gc.UnboundExpression;
                        gridColumn.ShowUnboundExpressionMenu = gc.ShowUnboundExpressionMenu;
                        gridColumn.GroupIndex = -1;

                        // OptionsColumn
                        gridColumn.OptionsColumn.AllowEdit = false;
                        gridColumn.OptionsColumn.AllowMove = false;
                        gridColumn.OptionsColumn.AllowSize = false;

                        // SummaryItem           
                        if (gc.SummaryItem.SummaryType != DevExpress.Data.SummaryItemType.None)
                        {
                            gridColumn.SummaryItem.FieldName = gc.SummaryItem.FieldName;
                            gridColumn.SummaryItem.SummaryType = gc.SummaryItem.SummaryType;
                            gridColumn.SummaryItem.DisplayFormat = gc.SummaryItem.DisplayFormat;

                            this.gridViewPreview.GroupSummary.Add(
                                gridColumn.SummaryItem.SummaryType,
                                gridColumn.SummaryItem.FieldName,
                                gridColumn,
                                gridColumn.SummaryItem.DisplayFormat
                            );
                        }

                        // DisplayFormat
                        gridColumn.DisplayFormat.FormatType = gc.DisplayFormat.FormatType;
                        gridColumn.DisplayFormat.FormatString = gc.DisplayFormat.FormatString;

                        // AppearanceCell
                        gridColumn.AppearanceCell.Options.UseTextOptions = true;
                        gridColumn.AppearanceCell.TextOptions.HAlignment = gc.AppearanceCell.TextOptions.HAlignment;

                        ColumnMap.Add(gc.FieldName, gridColumn);
                    }
                }

                // GroupedColumns
                if (gridView1.GroupedColumns.Count == 0)
                {
                    this.gridViewPreview.IndicatorWidth = 45;
                    this.gridViewPreview.CustomDrawRowIndicator += this.GridViewCustomDrawRowIndicator;
                }
                else
                {
                    foreach (GridColumn gc in gridView1.GroupedColumns)
                    {
                        ColumnMap[gc.FieldName].Group();
                    }
                }

                // FormatConditions
                foreach (StyleFormatCondition s in gridView1.FormatConditions)
                {
                    StyleFormatCondition sfc = new StyleFormatCondition();
                    this.gridViewPreview.FormatConditions.Add(sfc);

                    sfc.ApplyToRow = s.ApplyToRow;
                    sfc.Column = ColumnMap[s.Column.FieldName];
                    sfc.Condition = s.Condition;
                    sfc.Expression = s.Expression;
                    sfc.Value1 = s.Value1;
                    sfc.Value2 = s.Value2;

                    sfc.Appearance.BackColor = s.Appearance.BackColor;
                    sfc.Appearance.BackColor2 = s.Appearance.BackColor2;
                    sfc.Appearance.Font = s.Appearance.Font;
                }
                this.gridViewPreview.EndUpdate();
                this.gridControlPreview.EndUpdate();
                this.gridControlPreview.DataSource = ds.Tables[0].DefaultView;
            }
            else if (typeof(PivotGridControl) == control1.GetType())
            {
                PivotGridControl pivotGrid1 = (PivotGridControl)control1;

                this.pivotGridControlPreview.Visible = true;
                this.pivotGridControlPreview.Dock = DockStyle.Fill;

                // 按AreaIndex排序
                PivotGridField[] Fields = (PivotGridField[])new ArrayList(pivotGrid1.Fields).ToArray(typeof(PivotGridField));
                Array.Sort(Fields, delegate(PivotGridField f1, PivotGridField f2)
                {
                    return f1.AreaIndex.CompareTo(f2.AreaIndex);
                });

                this.pivotGridControlPreview.BeginUpdate();
                foreach (PivotGridField f in Fields)
                {
                    //if (f.Visible)
                    {
                        PivotGridField fieldPreview = this.pivotGridControlPreview.Fields.Add();
                        fieldPreview.Caption = f.Caption;
                        fieldPreview.FieldName = f.FieldName;
                        fieldPreview.Area = f.Area;
                        fieldPreview.AreaIndex = f.AreaIndex;
                        fieldPreview.Width = f.Width;
                        fieldPreview.Visible = f.Visible;
                        fieldPreview.Tag = f.Tag;

                        fieldPreview.UnboundType = f.UnboundType;
                        fieldPreview.UnboundExpression = f.UnboundExpression;
                        fieldPreview.SummaryType = f.SummaryType;
                        fieldPreview.TotalsVisibility = PivotTotalsVisibility.AutomaticTotals;

                        fieldPreview.CellFormat.FormatType = f.CellFormat.FormatType;
                        fieldPreview.CellFormat.FormatString = f.CellFormat.FormatString;

                        fieldPreview.Options.ShowUnboundExpressionMenu = f.Options.ShowUnboundExpressionMenu;
                        fieldPreview.Options.AllowEdit = false;
                    }
                }
                this.pivotGridControlPreview.EndUpdate();
                this.pivotGridControlPreview.DataSource = ds.Tables[0].DefaultView;
            }
        }

        private void wizardControl1_CancelClick(object sender, CancelEventArgs e)
        {
            this.Close();
        }

        void InitPivotGrid(TreeList treeList1, PivotGridControl pivotGridControl1, AsyncCompletedHandler asyncCompletedHandler1)
        {
            using (WaitDialogForm wdf = new WaitDialogForm())
            {
                wdf.Caption = "Initialize PivotGrid...";
                ResetPivotGrid(this.pivotGridControlDesigner);
                InitPivotGridAsync(treeList1, pivotGridControl1);

                DataSetFilledCallback callback = delegate(DataSet dataSet)
                {
                    if (dataSet == null)
                    {
                        asyncCompletedHandler1(null);
                        return;
                    }

                    pivotGridControl1.DataSource = new DataView(dataSet.Tables[0]);
                    pivotGridControl1.BestFit();
                };

                FillDataSetAsync(callback);
            }
        }

        void InitPivotGridAsync(TreeList treeList1, PivotGridControl pivotGridControl1)
        {
            treeList1.CloseEditor();

            DataTable dt = (DataTable)treeList1.DataSource;
            foreach (DataRow dr in dt.Rows)
            {
                Boolean fieldVisible = Convert.ToBoolean(dr[colFieldVisible.FieldName]);
                String fieldSummaryType = Convert.ToString(dr[colFieldSummaryType.FieldName]);
                String fieldName = Convert.ToString(dr[colFieldName.FieldName]);
                String fieldCaption = Convert.ToString(dr[colFieldCaption.FieldName]);
                String fieldDataType = Convert.ToString(dr[colFieldDataType.FieldName]);
                String fieldFormatString = Convert.ToString(dr[colFieldFormatString.FieldName]);
                String fieldAggregation = Convert.ToString(dr[colFieldAggregation.FieldName]);

                if (fieldVisible)
                {
                    PivotGridField field = pivotGridControl1.Fields.Add();
                    field.FieldName = fieldName;
                    field.Caption = fieldCaption;
                    field.Visible = false;
                    field.AreaIndex = -1;
                    field.TotalsVisibility = PivotTotalsVisibility.AutomaticTotals;
                    field.Tag = fieldAggregation;

                    field.Width = Convert.ToInt32(dr[colFieldWidth.FieldName]);
                    field.UnboundType = DevExpress.Data.UnboundColumnType.Bound;

                    // CellFormat
                    field.CellFormat.FormatType = DevExpress.Utils.FormatType.Custom;
                    if (!String.IsNullOrEmpty(fieldFormatString))
                    {
                        field.CellFormat.FormatString = fieldFormatString;
                    }
                }
            }
            PivotGridRender.Apply(pivotGridControl1, ReportContents);
        }

        void InitGrid(TreeList treeList1, GridControl gridControl1, GridView gridView1, AsyncCompletedHandler asyncCompletedHandler1)
        {
            using (WaitDialogForm wdf = new WaitDialogForm())
            {
                wdf.Caption = "Initialize Grid...";
                ResetGrid(gridControl1, gridView1);
                InitGridAsync(treeList1, gridControl1, gridView1);

                DataSetFilledCallback callback = delegate(DataSet dataSet)
                {
                    if (dataSet == null)
                    {
                        asyncCompletedHandler1(null);
                        return;
                    }
                    //AsyncOperationResult
                    gridControl1.DataSource = new DataView(dataSet.Tables[0]);
                    gridView1.BestFitColumns();
                };

                FillDataSetAsync(callback);
            }
        }

        void InitGridAsync(TreeList treeList1, GridControl gridControl1, GridView gridView1)
        {
            treeList1.CloseEditor();

            int VisibleIndex = -1;
            gridControl1.BeginUpdate();
            gridView1.BeginUpdate();

            DataTable dt = (DataTable) treeList1.DataSource;
            foreach(DataRow dr in dt.Rows)
            {
                Boolean fieldVisible = Convert.ToBoolean(dr[colFieldVisible.FieldName]);
                String fieldSummaryType = Convert.ToString(dr[colFieldSummaryType.FieldName]);
                String fieldName = Convert.ToString(dr[colFieldName.FieldName]);
                String fieldCaption = Convert.ToString(dr[colFieldCaption.FieldName]);
                String fieldDataType = Convert.ToString(dr[colFieldDataType.FieldName]);
                String fieldFormatString = Convert.ToString(dr[colFieldFormatString.FieldName]);
                String Aggregation = Convert.ToString(dr[colFieldAggregation.FieldName]);
                int width = Convert.ToInt32(dr[colFieldWidth.FieldName]);

                if (fieldVisible)
                {
                    VisibleIndex++;
                }

                //if (fieldVisible)
                {
                    GridColumn gc = gridView1.Columns.Add();
                    gc.FieldName = fieldName;
                    gc.Caption = fieldCaption;
                    gc.Visible = fieldVisible;
                    gc.VisibleIndex = fieldVisible ? VisibleIndex : -1;
                    gc.Width = fieldVisible ? width : 0;
                    gc.Tag = Aggregation;

                    // OptionsColumn
                    gc.OptionsColumn.AllowEdit = false;

                    // DisplayFormat
                    gc.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom;
                    if (!String.IsNullOrEmpty(fieldFormatString))
                    {
                        gc.DisplayFormat.FormatString = fieldFormatString;
                    }

                    if (!String.IsNullOrEmpty(fieldSummaryType))
                    {
                        Type t = typeof(DevExpress.Data.SummaryItemType);
                        gc.SummaryItem.SummaryType = (DevExpress.Data.SummaryItemType)Enum.Parse(t, fieldSummaryType);
                        gc.SummaryItem.DisplayFormat = fieldFormatString;
                        gc.SummaryItem.FieldName = fieldName;

                        if (gc.SummaryItem.SummaryType != DevExpress.Data.SummaryItemType.None)
                        {
                            gridView1.OptionsView.ShowFooter = true;
                            gridView1.GroupSummary.Add(
                                gc.SummaryItem.SummaryType,
                                gc.FieldName,
                                gc,
                                gc.SummaryItem.DisplayFormat
                            );
                        }
                    }
                }
            }
            gridView1.EndUpdate();
            gridControl1.EndUpdate();

            GridRender.Apply(gridView1, ReportContents);
        }

        private void GridViewCustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e)
        {
            if (e.Info.IsRowIndicator)
            {
                e.Info.DisplayText = (1 + e.RowHandle).ToString();
                e.Info.ImageIndex = -1;
            }
        }

        private void edtDataModel_EditValueChanged(object sender, EventArgs e)
        {
            if (edtDataModel.EditValue == null)
            {
                MessageBox.Show("DataSource is null");
                return;
            }

            ModelName = Convert.ToString(edtDataModel.Properties.View.GetFocusedDataRow()["ModelName"]);
            ModelId = Convert.ToString(edtDataModel.Properties.View.GetFocusedDataRow()["ModelId"]);

            treeListFields.DataSource = null;
            treeListFields.Nodes.Clear();

            String xmlData = null, url = null, XPath = "";
            url = String.Format("/rest/report/model/field/find?modelId={0}", ModelId);
            xmlData = HttpHelper.DoGet(url, null);

            DataSet ds = new DataSet();
            ds.ReadXmlSchema(ConfigRoot + "DataModelField.xsd");
            ds.ReadXml(new StringReader(xmlData));
            treeListFields.DataSource = ds.Tables[0];
                        
            if (!String.IsNullOrEmpty(ReportContents))
            {
                List<TreeListNode> hiddenNodes = new List<TreeListNode>();

                treeListFields.BeginUpdate();

                // Formula
                XPath = "/Root/Columns/Column";
                XPathNodeIterator nodes = XMLHelper.CreateNavigator(ReportContents).Select(XPath);
                if (nodes.Count > 0)
                {
                    foreach (XPathNavigator node in nodes)
                    {
                        String expr = node.SelectSingleNode("UnboundExpression").Value;
                        if (!String.IsNullOrEmpty(expr))
                        {
                            TreeListNode exprNode = treeListFields.AppendNode(null, null);
                            exprNode[colFieldName] = node.SelectSingleNode("FieldName").Value;
                            exprNode[colFieldParentId] = "0";
                            exprNode[colFieldId] = VdrpUtils.getIdentity();
                            hiddenNodes.Add(exprNode);
                            exprNode.Visible = false;
                        }
                    }
                }

                DataTable dt = (DataTable)treeListFields.DataSource;
                dt.AcceptChanges();

                // 
                foreach (DataRow dr in dt.Rows)
                {
                    dr[colFieldVisible.FieldName] = false;
                    dr[colFieldCondition.FieldName] = false;
                }

                // 
                foreach (DataRow dr in dt.Rows)
                {
                    String FieldName = dr[colFieldName.FieldName].ToString();

                    // Visible
                    XPath = "/Root/Columns/Column[FieldName='{0}']/Visible";
                    String Visible = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    if ("1".Equals(Visible))
                    {
                        dr[colFieldVisible.FieldName] = true;
                    }

                    // GroupedColumn
                    XPath = "/Root/GroupedColumns/GroupedColumn[FieldName='{0}']/FieldName";
                    String GroupedColumn = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    if (!String.IsNullOrEmpty(GroupedColumn))
                    {
                        dr[colFieldVisible.FieldName] = true;
                    }

                    // Width
                    XPath = "/Root/Columns/Column[FieldName='{0}']/Width";
                    String Width = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    if (!String.IsNullOrEmpty(Width))
                    {
                        dr[colFieldWidth.FieldName] = Int32.Parse(Width);
                    }

                    // Caption
                    XPath = "/Root/Columns/Column[FieldName='{0}']/Caption";
                    String Caption = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    if (!String.IsNullOrEmpty(Caption))
                    {
                        dr[colFieldCaption.FieldName] = Caption;
                    }

                    // FormatString
                    XPath = "/Root/Columns/Column[FieldName='{0}']/FormatString";
                    String FormatString = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    if (!String.IsNullOrEmpty(FormatString))
                    {
                        dr[colFieldFormatString.FieldName] = FormatString;
                    }

                    // Aggregation
                    XPath = "/Root/Columns/Column[FieldName='{0}']/Aggregation";
                    String Aggregation = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    dr[colFieldAggregation.FieldName] = String.IsNullOrEmpty(Aggregation) ? "None" : Aggregation;

                    // SummaryType
                    XPath = "/Root/Columns/Column[FieldName='{0}']/SummaryType";
                    String SummaryType = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    dr[colFieldSummaryType.FieldName] = String.IsNullOrEmpty(SummaryType) ? "None" : SummaryType;

                    // QueryConditions
                    XPath = "/Root/QueryConditions/QueryCondition[FieldName='{0}']/Condition";
                    String Condition = XMLHelper.SelectSingleValue(ReportContents, String.Format(XPath, FieldName));
                    if ("1".Equals(Condition))
                    {
                        dr[colFieldCondition.FieldName] = true;
                    }
                }

                foreach (TreeListNode n in hiddenNodes)
                {
                    n.Visible = false;
                    n.Visible = false;
                }
                treeListFields.EndUpdate();
            }

        }

        private void btnSetExpression_Click(object sender, EventArgs e)
        {
            using (frmExpressionEditor frm = new frmExpressionEditor())
            {
                frm.Grid = this.gridControlDesigner.Visible ? this.gridControlDesigner : null;
                frm.PivotGrid = this.pivotGridControlDesigner.Visible ? this.pivotGridControlDesigner : null;
                if (frm.ShowDialog() == DialogResult.OK)
                {
                    // 
                }
            }
        }

        private void btnSetFormatCondition_Click(object sender, EventArgs e)
        {
            if (this.gridControlDesigner.Visible && this.gridViewDesigner.FocusedColumn != null)
            {
                using (frmFormatConditionsEditor frm = new frmFormatConditionsEditor())
                {
                    frm.GridColumn = this.gridViewDesigner.FocusedColumn;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        this.FindForm().Refresh();
                    }
                }
            }
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            this.gridControlPreview.DataSource = null;
            this.pivotGridControlPreview.DataSource = null;
        }

        private void cbcGridOptionsView_ItemCheck(object sender, DevExpress.XtraEditors.Controls.ItemCheckEventArgs e)
        {
            bool optionSet = e.State == CheckState.Checked ? true : false;
            string option = cbcGridOptionsView.GetDisplayItemValue(e.Index).ToString();
            DevExpress.Utils.SetOptions.SetOptionValueByString(option, this.gridViewDesigner.OptionsView, optionSet);
        }

        private void btnSaveTo_Click(object sender, EventArgs e)
        {
            FontConverter fc = new FontConverter();

            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            sb.Append("<Root>");
            sb.Append("<Report>");
            sb.Append(String.Format("<Id>{0}</Id>", ReportId));
            sb.Append(String.Format("<ParentId>{0}</ParentId>", ReportParentId));
            sb.Append(String.Format("<Caption>{0}</Caption>", ReportCaption));
            sb.Append(String.Format("<Comments>{0}</Comments>", ReportComments));
            sb.Append(String.Format("<ModelId>{0}</ModelId>", ModelId));
            sb.Append(String.Format("<Type>{0}</Type>", ReportType));
            sb.Append("<Contents><![CDATA[<?xml version=\"1.0\" encoding=\"utf-8\"?><Root>");
            if (TYPE_PIVOT.Equals(ReportType))
            {
                sb.Append("<Columns>");
                foreach (PivotGridField f in this.pivotGridControlPreview.Fields)
                {
                    sb.Append("<Column>");
                    sb.Append(String.Format("<Name>{0}</Name>", String.IsNullOrEmpty(f.Name) ? "field" + f.FieldName : f.Name));
                    sb.Append(String.Format("<Aggregation>{0}</Aggregation>", f.Tag));
                    sb.Append(String.Format("<Caption>{0}</Caption>", f.Caption));
                    sb.Append(String.Format("<FieldName>{0}</FieldName>", f.FieldName));
                    sb.Append(String.Format("<Visible>{0}</Visible>", "1"));
                    sb.Append(String.Format("<Area>{0}</Area>", f.Area));
                    sb.Append(String.Format("<AreaIndex>{0}</AreaIndex>", f.Visible ? f.AreaIndex : -1));
                    sb.Append(String.Format("<Width>{0}</Width>", f.Width));
                    sb.Append(String.Format("<UnboundType>{0}</UnboundType>", f.UnboundType));
                    sb.Append(String.Format("<UnboundExpression>{0}</UnboundExpression>", f.UnboundExpression));
                    sb.Append(String.Format("<SummaryType>{0}</SummaryType>", f.SummaryType));
                    sb.Append(String.Format("<TotalsVisibility>{0}</TotalsVisibility>", f.TotalsVisibility));
                    sb.Append(String.Format("<FormatType>{0}</FormatType>", f.CellFormat.FormatType));
                    sb.Append(String.Format("<FormatString>{0}</FormatString>", f.CellFormat.FormatString));
                    sb.Append("</Column>");
                }
                sb.Append("</Columns>");
            }
            else if (TYPE_TABLE.Equals(ReportType))
            {
                GridView gridView1 = this.gridViewPreview;

                // GroupedColumns
                List<String> GroupedColumns = new List<string>();
                if (gridView1.GroupedColumns.Count > 0)
                {
                    foreach (GridColumn gc in gridView1.GroupedColumns)
                    {
                        GroupedColumns.Add(gc.FieldName);
                    }
                }

                // Columns
                sb.Append("<Columns>");
                foreach (GridColumn gc in gridView1.Columns)
                {
                    if (gc.Visible || GroupedColumns.Contains(gc.FieldName))
                    {
                        sb.Append("<Column>");
                        sb.Append(String.Format("<Name>{0}</Name>", String.IsNullOrEmpty(gc.Name) ? "field" + gc.FieldName : gc.Name));
                        sb.Append(String.Format("<Aggregation>{0}</Aggregation>", gc.Tag));
                        sb.Append(String.Format("<Caption>{0}</Caption>", gc.Caption));
                        sb.Append(String.Format("<FieldName>{0}</FieldName>", gc.FieldName));
                        sb.Append(String.Format("<Visible>{0}</Visible>", "1"));
                        sb.Append(String.Format("<VisibleIndex>{0}</VisibleIndex>", GroupedColumns.Contains(gc.FieldName) ? -1 : gc.VisibleIndex));
                        sb.Append(String.Format("<Width>{0}</Width>", gc.Width));
                        sb.Append(String.Format("<UnboundType>{0}</UnboundType>", gc.UnboundType));
                        sb.Append(String.Format("<UnboundExpression>{0}</UnboundExpression>", gc.UnboundExpression));

                        // FormatType
                        sb.Append(String.Format("<FormatType>{0}</FormatType>", gc.DisplayFormat.FormatType));
                        if (gc.DisplayFormat.FormatType != FormatType.None)
                        {
                            sb.Append(String.Format("<FormatString>{0}</FormatString>", gc.DisplayFormat.FormatString));
                        }
                        else
                        {
                            sb.Append(String.Format("<FormatString>{0}</FormatString>", ""));
                        }

                        // SummaryType
                        sb.Append(String.Format("<SummaryType>{0}</SummaryType>", gc.SummaryItem.SummaryType));
                        if (gc.SummaryItem.SummaryType != DevExpress.Data.SummaryItemType.None)
                        {
                            sb.Append(String.Format("<SummaryDisplayFormat>{0}</SummaryDisplayFormat>", gc.SummaryItem.DisplayFormat));
                            sb.Append(String.Format("<SummaryFieldName>{0}</SummaryFieldName>", gc.SummaryItem.FieldName));
                        }
                        else
                        {
                            sb.Append(String.Format("<SummaryDisplayFormat>{0}</SummaryDisplayFormat>", ""));
                            sb.Append(String.Format("<SummaryFieldName>{0}</SummaryFieldName>", ""));
                        }

                        sb.Append("</Column>");
                    }
                }
                sb.Append("</Columns>");

                // GroupedColumns
                if (GroupedColumns.Count > 0)
                {
                    sb.Append("<GroupedColumns>");
                    foreach (String gc in GroupedColumns)
                    {
                        sb.Append("<GroupedColumn>");
                        sb.Append(String.Format("<FieldName>{0}</FieldName>", gc));
                        sb.Append("</GroupedColumn>");
                    }
                    sb.Append("</GroupedColumns>");
                }

                // FormatConditions
                if (gridView1.FormatConditions.Count > 0)
                {
                    sb.Append("<FormatConditions>");
                    foreach (StyleFormatCondition sfc in gridView1.FormatConditions)
                    {
                        sb.Append("<FormatCondition>");
                        sb.Append(String.Format("<FieldName>{0}</FieldName>", sfc.Column.FieldName));
                        sb.Append(String.Format("<ApplyToRow>{0}</ApplyToRow>", sfc.ApplyToRow));
                        sb.Append(String.Format("<Condition>{0}</Condition>", sfc.Condition));
                        sb.Append(String.Format("<Value1>{0}</Value1>", sfc.Value1));
                        sb.Append(String.Format("<TypeOfValue1>{0}</TypeOfValue1>", sfc.Value1 == null ? typeof(String) : sfc.Value1.GetType()));
                        sb.Append(String.Format("<Value2>{0}</Value2>", sfc.Value2));
                        sb.Append(String.Format("<TypeOfValue2>{0}</TypeOfValue2>", sfc.Value2 == null ? typeof(String) : sfc.Value2.GetType()));
                        sb.Append(String.Format("<BackColor>{0}</BackColor>", ColorTranslator.ToHtml(sfc.Appearance.BackColor)));
                        sb.Append(String.Format("<BackColor2>{0}</BackColor2>", ColorTranslator.ToHtml(sfc.Appearance.BackColor2)));
                        sb.Append(String.Format("<Font>{0}</Font>", fc.ConvertToString(sfc.Appearance.Font)));
                        sb.Append("</FormatCondition>");
                    }
                    sb.Append("</FormatConditions>");
                }

                // gridView1.OptionsView
                sb.Append("<OptionsViews>");
                foreach (CheckedListBoxItem item in cbcGridOptionsView.Items)
                {
                    sb.Append("<OptionsView>");
                    sb.Append(String.Format("<Name>{0}</Name>", item.Value.ToString()));
                    sb.Append(String.Format("<Value>{0}</Value>", item.CheckState == CheckState.Checked ? "1" : "0"));
                    sb.Append("</OptionsView>");
                }
                sb.Append("</OptionsViews>");
            }

            // QueryConditions
            treeListFields.CloseEditor();
            DataTable dt = (DataTable)treeListFields.DataSource;
            sb.Append("<QueryConditions>");
            foreach(DataRow dr in dt.Rows)
            {
                if (Convert.ToBoolean(dr[colFieldCondition.FieldName]))
                {
                    sb.Append("<QueryCondition>");
                    sb.Append(String.Format("<FieldName>{0}</FieldName>", dr[colFieldName.FieldName]));
                    sb.Append(String.Format("<Condition>{0}</Condition>", "1"));
                    sb.Append("</QueryCondition>");
                }
            }
            sb.Append("</QueryConditions>");

            sb.Append("</Root>]]></Contents>");
            sb.Append("</Report>");
            sb.Append("</Root>");
            //File.WriteAllText("c:/rd.xml", sb.ToString());
            try
            {
                String dc = this.getDefaultCriteria();

                if (isNew)
                {
                    HttpHelper.DoPost("/rest/report/custom/add", sb.ToString(), null);
                    isNew = !isNew;
                }
                else
                {
                    // Default Criteria
                    HttpHelper.DoPost("/rest/report/custom/criteria/delete", dc, null);
                    HttpHelper.DoPost("/rest/report/custom/update", sb.ToString(), null);
                }
                HttpHelper.DoPost("/rest/report/custom/criteria/add", dc, null);

                filter = null;
                Modified = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private frmReportFilter filter = null;
        private void btnFilter_Click(object sender, EventArgs e)
        {
            //
            String xmlData = "";

            if (filter == null)
            {
                filter = new frmReportFilter();
            }

            filter.ReportId = ReportId;
            filter.DataModel = ModelName;
            filter.Fields = frmReportFilter.GetFields(DataSetControl);
            if (filter.ShowDialog() == DialogResult.OK)
            {
                xmlData = filter.FilterString;
                xmlData = HttpHelper.DoPost("/rest/report/custom/query", xmlData, null);
                //File.WriteAllText("c:/" + ReportCaption + ".xml" , xmlData);
                DataSet ds = new DataSet();
                ds.ReadXmlSchema(ConfigRoot + ModelName + ".xsd");
                ds.ReadXml(new StringReader(xmlData));

                if (TYPE_TABLE.Equals(ReportType))
                {
                    this.gridControlPreview.DataSource = ds.Tables[0];
                }
                else if (TYPE_PIVOT.Equals(ReportType))
                {
                    this.pivotGridControlPreview.DataSource = ds.Tables[0];
                }
            }
        }

        private void frmReportDesign_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (filter != null)
            {
                filter.Dispose();
                filter = null;
            }
        }

        private String getDefaultCriteria()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            sb.Append("<Root>");
            sb.Append("<ReportCriteria>");
            sb.Append(String.Format("<Id>{0}</Id>", ReportId));
            sb.Append(String.Format("<CriteriaName>{0}</CriteriaName>", "默认"));
            sb.Append(String.Format("<CriteriaType>Basic,{0}</CriteriaType>", ReportId));
            sb.Append(String.Format("<ReportId>{0}</ReportId>", ReportId));
            sb.Append(String.Format("<UserId>{0}</UserId>", "0"));
            sb.Append("<Contents><![CDATA[<?xml version=\"1.0\" encoding=\"utf-8\"?><Root>");
            DataTable dt = (DataTable)treeListFields.DataSource;
            foreach (DataRow dr in dt.Rows)
            {
                if (Convert.ToBoolean(dr[colFieldCondition.FieldName]))
                {
                    String Ops = (String)dr["FieldOps"];
                    sb.Append("<Field>");
                    sb.Append(String.Format("<Name>{0}</Name>", dr[colFieldName.FieldName]));
                    sb.Append(String.Format("<Caption>{0}</Caption>", dr[colFieldCaption.FieldName]));
                    sb.Append(String.Format("<DataType>{0}</DataType>", dr[colFieldDataType.FieldName]));
                    sb.Append(String.Format("<Op>{0}</Op>", Ops.Split(',')[0]));
                    sb.Append(String.Format("<Ops>{0}</Ops>", Ops));
                    sb.Append(String.Format("<Value1>{0}</Value1>", ""));
                    sb.Append(String.Format("<Value2>{0}</Value2>", ""));
                    sb.Append("</Field>");
                }
            }
            sb.Append("</Root>]]></Contents>");
            sb.Append("</ReportCriteria>");
            sb.Append("</Root>");

            return sb.ToString();
        }

        private void frmReportDesign_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.DialogResult = this.Modified ? DialogResult.OK : DialogResult.Cancel;
        }

        private void treeListFields_BeforeFocusNode(object sender, BeforeFocusNodeEventArgs e)
        {
            //
            colFieldVisible.OptionsColumn.AllowEdit = !e.Node.HasChildren;
            colFieldCaption.OptionsColumn.AllowEdit = !e.Node.HasChildren;
            colFieldFormatString.OptionsColumn.AllowEdit = !e.Node.HasChildren;
            colFieldCondition.OptionsColumn.AllowEdit = !e.Node.HasChildren;
            colFieldWidth.OptionsColumn.AllowEdit = !e.Node.HasChildren;

            // 
            colFieldAggregation.OptionsColumn.AllowEdit = e.Node.StateImageIndex == 0 && !e.Node.HasChildren;
        }

        private void treeListFields_GetStateImage(object sender, GetStateImageEventArgs e)
        {
            String d = e.Node.RootNode[colFieldDataType].ToString();

            if ("measure".Equals(d))
            {
                e.Node.StateImageIndex = 0;
            }
            else if ("dimension".Equals(d))
            {
                e.Node.StateImageIndex = e.Node.HasChildren ? 1 : 2;
            }
        }

    }

}